import java.util.Stack;
import java.util.ArrayList;

/**
 * The Botclass holds info of a bot such as the instructions
 * that decides which direction it will go. It also contains an method
 * to execute the program and return the direction the bot decides to go.
 * @author Patrik
 *
 */
public class Bot {
	ArrayList<InstructionInterface> instructions;
	int playerId;
	String name;
	Stack<Integer> stack;
	IntWrapper[] register;
	
	/**
	 * 
	 * @param filename the filename of the file that contains the
	 * instructions for the bot. 
	 * @param playerId the player number which this bot is given. This
	 * is the number that is stored on all the positions on the gamemap
	 * that this bot visits.
	 */
	public Bot(String filename, int playerId) throws Exception{
		name=filename.substring(0,filename.length()-4);
		this.playerId=playerId;
		instructions=new ArrayList<InstructionInterface>();
		stack=new Stack<Integer>();
		register=new IntWrapper[1024];
		resetRegisters();
		instructions=new InstructionParser(filename,playerId).parseFile(register);
		
	}
	
	/**
	 * Execute the program and returns the direction the bot wishes to
	 * go in.
	 * @return direction 0=east 1=north 2=west 4=south
	 */
	public GameMap.Direction getDirection(){
		Integer nexti;
		for(int i=0, a=0;i<instructions.size()&&a<1000;i++,a++){
			nexti=instructions.get(i).act();
			if(nexti==null){
				//Do nothing
			}
			else{
				if(instructions.get(i) instanceof CallInstruction){
					stack.push(new Integer(i));
					i=nexti;
				}
				else if(instructions.get(i) instanceof RetInstruction
						&&!stack.isEmpty()){
					i=stack.pop();
				}
				else{
					i=nexti-1;//TODO check jumps
				}
			}
		}
		if(register[0]!=null){
			return GameMap.Direction.values()[register[0].get()%4];
		}
		return GameMap.Direction.UP;
	}
	
	/**
	 * @return playerId
	 */
	public int getPlayerNumber(){
		return playerId;
	}
	
	/**
	 * 
	 * @return botname (filename)
	 */
	public String getName(){
		return name;
	}
	
	public void resetRegisters(){
		for(int i=0;i<1024;i++){
			if(register[i]==null)
			register[i]=new IntWrapper(0);
			else{
				register[i].set(0);
			}
		}
	}
}
